package helper

import (
	"Hypnos-Soundcore/constants"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"net/url"
	"reflect"
	"time"
)

// BaseResponse http response base struct
type BaseResponse struct {
	Code int    `json:"code" swaggo:"true,返回码"`
	Msg  string `json:"msg" swaggo:"true,返回消息,成功"`
}

// Response http response base struct
type Response struct {
	Code int         `json:"code" swaggo:"true,返回码"`
	Msg  string      `json:"msg" swaggo:"true,返回消息,成功"`
	Data interface{} `json:"data,omitempty"`
}

// QueryOutline .
type QueryOutline struct {
	Total int64 `json:"total" swaggo:"false,总个数"`
}

// OutlineResponse http response base struct
type OutlineResponse struct {
	Response
	Outline interface{} `json:"outline,omitempty"`
}

// StatusResponse http error status response
type StatusResponse struct {
	Status   int
	Response interface{}
}

type DynamicDataResponse struct {
	ShortLink   string
	PreviewLink string
}

// BuildStatusResponse .
func BuildStatusResponse(status, code int, message string) interface{} {
	return BuildStatusResponseByLanguage(status, code, message, constants.LangEn)
}

// BuildResponseV1 build response v1
func BuildResponseV1(code int) interface{} {
	return BuildResponseByLanguageV1(code, constants.LangEn)
}

// BuildResponseV2 build response v2
func BuildResponseV2(code int, msg string) interface{} {
	return BuildResponseByLanguageV2(code, msg, constants.LangEn)
}

// BuildResponseV3 build response v3
func BuildResponseV3(code int, data interface{}) interface{} {
	return BuildResponseByLanguageV3(code, constants.LangEn, data)
}

// BuildResponseV4 build response v4
func BuildResponseV4(code int, msg string, data interface{}) interface{} {
	return BuildResponseByLanguageV4(code, msg, constants.LangEn, data)
}

// BuildOutlineResponse build outline response
func BuildOutlineResponse(code int, msg string, data interface{}, outline interface{}) interface{} {
	return BuildOutlineResponseByLanguage(code, msg, constants.LangEn, data, outline)
}

// PrintRequestLatency 将请求相关信息写到日志文件中供后台抓取分析
func PrintRequestLatency(start time.Time, c *gin.Context) {
	var ibaseRequest constants.IBaseRequest
	var iextraRequest *constants.ExtraRequest
	//statusCode := c.Writer.Status()
	latency := time.Now().Sub(start)
	if br, ok := c.Get(constants.KeyBaseRequest); ok {
		ibaseRequest, _ = br.(constants.IBaseRequest)
	}
	if er, ok := c.Get(constants.KeyExtraRequest); ok {
		if iextraRequest, _ = er.(*constants.ExtraRequest); iextraRequest != nil {
			iextraRequest.ExLatency = int64(latency)
		}
	}
	if ibaseRequest != nil && iextraRequest != nil {
		// 将api请求按json格式写入文件中，优化日志采集方式
		ar := constants.BuildApiRequest(ibaseRequest, iextraRequest)
		if bytes, err := json.Marshal(ar); err == nil {
			ApiPrintln(bytes)
		}
		//DebugAccessPrintln(ibaseRequest, iextraRequest)
	}
}

// BuildErrMsg 自定义错误码和消息
func BuildErrMsg(code int, err error) (ret string) {
	if err != nil {
		ret = fmt.Sprintf("%s, %s", constants.GetTextByCodeDefault(code), err.Error())
	}
	return
}

// PanicResponseV1 返回自定义错误码
func PanicResponseV1(code int) {
	panic(BuildResponseV1(code))
}

// PanicResponseByLanguageV1 返回自定义错误码
func PanicResponseByLanguageV1(code int, lang string) {
	panic(BuildResponseByLanguageV1(code, lang))
}

// PanicResponseV2 返回自定义错误码
func PanicResponseV2(code int, msg string) {
	panic(BuildResponseV2(code, msg))
}

// PanicErrorResponse 返回自定义错误码和消息
func PanicErrorResponse(code int, err error) {
	if err == nil {
		PanicResponseV1(code)
	} else {
		msg := fmt.Sprintf("%s %s", constants.GetTextByCodeDefault(code), err.Error())
		PanicResponseV2(code, msg)
	}
}

// PanicStatus 返回HTTP状态码
func PanicStatus(status, code int, message string) {
	panic(BuildStatusResponse(status, code, message))
}

// IsValidURL 是否有效URL
func IsValidURL(rawurl string) bool {
	parseURL, err := url.Parse(rawurl)
	return (err == nil && parseURL != nil && len(parseURL.Scheme) > 0)
}

func parsePresetHeaders(c *gin.Context, obj interface{}) {
	val := reflect.ValueOf(obj)
	s := val.Elem()
	if s.Kind() == reflect.Struct {
		for _, field := range constants.PresetHeaders {
			if value := c.GetHeader(field.HeaderKey); len(value) > 0 {
				if f := s.FieldByName(field.HeaderField); f.IsValid() && f.CanSet() {
					if f.Kind() == reflect.String {
						f.SetString(value)
					}
				}
			}
		}
	}
}

// PrintRecoverLatency 将请求异常信息写到日志文件中供后台抓取分析
func PrintRecoverLatency(start time.Time, errMsg, message string, c *gin.Context) {
	latency := time.Now().Sub(start)
	ibaseRequest := &constants.BaseRequest{}
	parsePresetHeaders(c, ibaseRequest)
	iextraRequest := &constants.ExtraRequest{ExPath: c.Request.URL.Path, ExLatency: int64(latency),
		ExMessage: errMsg, ExParams: message, ExCode: constants.CodeSystemException}
	ErrorAccessPrintln(ibaseRequest, iextraRequest)
}
